﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using aboveXWords.Properties;

namespace aboveXWords.GUI
{
  [Serializable]
  public class Squares : List<Square>
  {
    public Squares(IEnumerable<Square> selected)
    {
      AddRange(selected);
    }

    public Squares()
    {
    }

    public virtual bool Select
    {
      set
      {
        foreach (Square square in this)
          square.Selected = value;
      }
    }

    public Squares Selected
    {
      get { return new Squares(this.Where(square => square.Selected).ToArray()); }
    }

    public Square Hovered
    {
      get { return this.FirstOrDefault(square => square.Hover); }
    }

    public Square Hit(MouseEventArgs mouseEventArgs)
    {
      return this.FirstOrDefault(square => square.Hit(mouseEventArgs));
    }

    internal void InvalidateSelected(Canvas canvas)
    {
      foreach (Square square in this)
        square.InvalidateSelected(canvas);
    }

    public void Invalidate(Canvas canvas)
    {
      foreach (Square square in this)
        square.Invalidate(canvas);
    }

    public void Unselect(Canvas canvas)
    {
      foreach (Square square in this)
        square.Unselect(canvas);
    }

    public void Unhover(Canvas canvas)
    {
      foreach (Square square in this)
        square.Unhover(canvas);
    }

    public virtual Cursor Move(Canvas canvas, MouseEventArgs mouseEventArgs, MouseEventArgs mouseDownPosition)
    {
      if (Count == 0) return canvas.Cursor;
      if (Count == 1)
        return this[0].Move(canvas, mouseEventArgs, mouseDownPosition);
      //if (Count == 2)
      //  return this[0].Move(canvas, mouseEventArgs, mouseDownPosition); // todo - handle hit with two selected move both
      foreach (Square square in this)
        square.Move(canvas, mouseEventArgs, mouseDownPosition);
      return Cursors.Hand;
    }

    internal virtual void Paint(Graphics graphics)
    {
      foreach (Square square in this)
        square.Paint(graphics);
    }

    public Squares SquaresAt(Square square)
    {
      return new Squares(this.Where(sq => sq.Contains(square)).ToArray());
    }

    /// <summary>
    /// Snap to the grid.
    /// Locate a square with original size and calculate the snap-distance.
    /// </summary>
    /// <returns></returns>
    public PointF Snap()
    {
      PointF snap = new PointF();
      foreach(Square square in this)
        if (square.Rectangle.Width == Settings.Default.SquareSize.Width &&
           square.Rectangle.Height == Settings.Default.SquareSize.Height)
        {
          double deltaX = square.Rectangle.Left -
                          Settings.Default.SquareSize.Width*
                          Math.Truncate(square.Rectangle.Left/Settings.Default.SquareSize.Width);
          if (deltaX > Settings.Default.SquareSize.Width/2) deltaX -= Settings.Default.SquareSize.Width;

          double deltaY = square.Rectangle.Top -
                          Settings.Default.SquareSize.Height*
                          Math.Truncate(square.Rectangle.Top/Settings.Default.SquareSize.Height);
          if (deltaY > Settings.Default.SquareSize.Width/2) deltaY -= Settings.Default.SquareSize.Height;
          snap = new PointF((float) deltaX, (float) deltaY);
        }
      return snap;
    }
  }
}